#ifndef __SYSTEM_H__
#define __SYSTEM_H__

#include "FreeRTOS.h"
#include "LoRaMac.h"
#include "queue.h"
#include "semphr.h"
#include "task.h"
#include "timer.h"
#include "timers.h"
#include "utilities.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define CONFIG_DTU_485  // 使用DTU485设备
// #define CONFIG_DTU_AI    // 使用AI设备
// #define CONFIG_DTU_DOUT  // 使用Dout设备
// #define CONFIG_DTU_DIN   // 使用DIN设备

#define CL_OK (0)
#define CL_FAIL (-1)
#define CL_TRUE 1
#define CL_FALSE 0

#define SYSTEM_DEVICE_NUM (32)
#define DEVICE_MODEL_NUM (6)
#define SYSTEM_ATTRIBUTE_NUM (10)      // 系统属性个数
#define SYSTEM_AI_ATTRIBUTE_NUM (4)    // 系统AI属性个数
#define SYSTEM_DOUT_ATTRIBUTE_NUM (2)  // 系统Dout属性个数
#define SYSTEM_DIN_ATTRIBUTE_NUM (4)   // 系统Din属性个数

#if defined(CONFIG_DTU_485)
#    define RS485_APP_DATA_NUM (4)  // 485队列长度
#endif

#define USE_LORAWAN_ABP (0)

#define LORAWAN_APP_DATA_NUM (5)        // LORA数据的队列长度
#define LORAWAN_APP_DATA_MAX_SIZE (64)  // APP数据缓冲区

#define DEVICEEUI_LEN (8)  // DeviceEUI的长度
#define APPEUI_LEN (8)     // APPEUI的长度
#define APPKEY_LEN (16)    // APPKey的长度
#define APPSKEY_LEN (16)   // APPSKey的长度
#define NWKSKEY_LEN (16)   // NwkSkey的长度

#define APP_TX_DUTYCYCLE (10000)     // 应用发送占空比 5S
#define APP_TX_DUTYCYCLE_RND (1000)  // 应用发送的随机占空比时间

#define LORAWAN_DEFAULT_DATARATE (DR_0)  // 默认的数据速率
#define LORAWAN_DATANBTRIALS (3)         // 默认的发送数据重复次数

#define LORAWAN_CONFIRMED_MSG_ON (true)  // 默认消息确认的控制
#define LORAWAN_ADR_ON (1)               // 默认自适应数据速率
#define LORAWAN_APP_PORT (2)             // 默认的发送数据的端口号

#define LORAWAN_DEFAULT_RX2_FREQUENCY (505300000)  // RX2接收窗口参数频率
#define LORAWAN_DEFAULT_RX2_DATARATE (DR_0)        // RX2接收窗口参数数据速率

#define SoftwareVersion "DTU_LORAWAN1.1_CN470_V1.0.0"

#define TaskInit_Stack_SIZE (32)
/*系统任务*/
#define APP_Service_TASK_DELAY_MS ((TickType_t)50)
#define APP_Service_TASK_PRIORITY (tskIDLE_PRIORITY + 4)
#define APP_Service_TASK_STACK_SIZE (TaskInit_Stack_SIZE * 4)

/*LoRa任务*/
#define APP_LORA_TASK_DELAY_MS ((TickType_t)20)
#define APP_LORA_TASK_PRIORITY (tskIDLE_PRIORITY + 6)
#define APP_LORA_TASK_STACK_SIZE (TaskInit_Stack_SIZE * 6)

/*发送数据检测任务*/
#define APP_SEND_DATA_TASK_DELAY_MS ((TickType_t)500)
#define APP_SEND_DATA_TASK_PRIORITY (tskIDLE_PRIORITY + 6)
#define APP_SEND_DATA_TASK_STACK_SIZE (TaskInit_Stack_SIZE * 5)

/*485任务*/
#define APP_485_TASK_DELAY_MS ((TickType_t)50)
#define APP_485_TASK_PRIORITY (tskIDLE_PRIORITY + 8)
#define APP_485_TASK_STACK_SIZE (TaskInit_Stack_SIZE * 7)

enum {
    ATTR_ALARM_IDLE = 0x00,  // 属性告警状态空闲
    ATTR_ALARM_MIN = 0x01,   // 属性告警低于告警下限
    ATTR_ALARM_MAX = 0x02,   // 属性告警高于告警上线
};

enum {
    ATTR_IDLE = 0x00,  // 采样数据状态空闲
    ATTR_SET
};

#pragma pack(1)

#if defined(CONFIG_DTU_485)
typedef struct {
    uint8_t attrId;  // 属性ID号
    // uint32_t attrAlarmMinData;                                //属性下限值
    // uint32_t attrAlarmMaxData;                                //属性上限值
    // uint32_t attrAlarmRecoverMinData;                        //属性回复下限值
    // uint32_t attrAlarmRecoverMaxData;                        //属性回复上限值
    // uint32_t attrCreatTime;                                    //属性创建的时间 UTC时间
    // uint16_t sampleTime;                                    //采样时间，单位s

    // uint8_t  attrSlaveAddr;                                 //从机地址1字节
    // uint8_t  attrCmd;                                       //功能码1字节
    // uint16_t attrRegaddr;                                   //寄存器地址2字节
    // uint16_t attrRegnum;                                    //寄存器数量2字节
    // uint8_t     attrResultOffset;                                //取返回值的偏移量；
    // uint8_t  attrResultType;                                //返回值的类型
    uint8_t attrCmd[16];
    uint8_t attrCmdLen : 4;
    uint8_t attrVerify : 4;  // 校验方式, 默认CRC
    uint8_t attrVerifyOffset : 4;
    uint8_t attrAddrOffset : 4;
    uint8_t attrRegOffset : 4;
} SystemAttributeData_t;
#endif

#if defined(CONFIG_DTU_AI)
typedef struct {
    uint8_t attrId;                    // 属性ID号
    uint32_t attrAlarmMinData;         // 属性下限值
    uint32_t attrAlarmMaxData;         // 属性上限值
    uint32_t attrAlarmRecoverMinData;  // 属性回复下限值
    uint32_t attrAlarmRecoverMaxData;  // 属性回复上限值
    uint16_t sampleTime;               // 采样时间，单位s
} SystemAiAttributeData_t;
#endif

#if defined(CONFIG_DTU_DOUT) || defined(CONFIG_DTU_DIN)
typedef struct {
    uint8_t attrId;     // 属性ID号
    uint32_t attrData;  // 属性值
} SystemDinDoutAttributeData_t;
#endif

typedef struct {
    uint8_t acqType;  // 类型
    uint8_t regAddr[4];
    uint8_t regLengh : 4;
    uint8_t dataOffset : 5;
    uint8_t dataLen : 3;
} LoraModel_t;

typedef struct {
    int32_t baudRate;
    uint8_t parityMode : 2;
    uint8_t stopBits : 2;
    uint8_t dataWidth : 4;
} LoraTransport_t;

#define LORAMODEL_MAX_NUM 8
typedef struct {
    uint8_t modelId;  // 型号ID
    uint8_t attrId;   // 关联的协议
    LoraModel_t model[LORAMODEL_MAX_NUM];
} LoraDeviceModel_t;

typedef struct {
    uint8_t modelId;  // 关联的型号
    uint8_t addrLength;
    uint8_t devAddr[8];
    // LoraTransport_t transport;
} LoraDevice_t;

typedef struct {
    volatile uint8_t devEui[DEVICEEUI_LEN];  // 设备EUI  终端设备ID
    volatile uint8_t appEui[APPEUI_LEN];     // 应用唯一识别ID
    volatile uint8_t appKey[APPKEY_LEN];     // 应用密钥

#if (USE_LORAWAN_ABP == 1)
    volatile uint8_t nwkSKey[NWKSKEY_LEN];  // 网络回话密钥
    volatile uint8_t appSKey[APPSKEY_LEN];  // 应用回话密钥
    volatile uint32_t devAddr;
    volatile uint8_t netID;
#endif

    volatile uint8_t activitionType;   // 入网的方式
    volatile uint8_t txConfirmedType;  // 是否需要回复确认消息
    volatile int8_t appDataRate;       // 发送数据的时候设置的数据速率
    volatile uint8_t appDataNbTrials;  // 发送confirm消息的重复次数
    volatile uint8_t adrType;          // 设置是否开启数据速率优化

    volatile uint8_t appPort;  // 发送数据的端口号
    volatile uint8_t power;    // 发送数据的功率

    volatile Rx2ChannelParams_t rx2Channel;  // rx2接收窗口的参数，用于入网时候使用
    volatile uint16_t channelsMask[6];       // 信道配置参数
    volatile DeviceClass_t deviceClass;      // 设备的类型

    volatile uint32_t baudRate : 24;      // 波特率
    volatile uint32_t dataWidth : 4;      // 数据宽度
    volatile uint32_t stopBit : 2;        // 停止位
    volatile uint32_t parityMode : 2;     // 校验方式
    volatile uint8_t perferChannel;       // 优选信道
    volatile uint8_t perferChannelIndex;  // 优选信道索引
    volatile uint8_t perferDataRate;      // 优选信道数据速率
    volatile uint16_t txDutyCycleTime;    // 发送数据的间隔时间，单位s

    LoraDevice_t loraDevice[SYSTEM_DEVICE_NUM];  // 设备
    LoraDeviceModel_t deviceModel[DEVICE_MODEL_NUM];

#if defined(CONFIG_DTU_485)
    SystemAttributeData_t attributeData[SYSTEM_ATTRIBUTE_NUM];  // 属性
#endif

#if defined(CONFIG_DTU_AI)
    SystemAiAttributeData_t aiAttrData[SYSTEM_AI_ATTRIBUTE_NUM];  // AI属性
#endif

#if defined(CONFIG_DTU_DOUT)
    SystemDinDoutAttributeData_t doutAttrData[SYSTEM_DOUT_ATTRIBUTE_NUM];  // DOUT属性
#endif

#if defined(CONFIG_DTU_DOUT)
    SystemDinDoutAttributeData_t dinAttrData[SYSTEM_DIN_ATTRIBUTE_NUM];  // DIN属性
#endif
    volatile uint8_t crc;
} SystemParmData_t;

#define SYSTEM_ATTR_OFFSET (sizeof(SystemParmData_t) + (8 - (sizeof(SystemParmData_t) % 8)) + 8)
// typedef SystemAttribute_t ;

typedef union {
    uint16_t state;
    struct {
        uint8_t loraTxRunning : 1;    // 正在发送数据
        uint8_t loraTxSuccess : 1;    // 发送数据成功
        uint8_t loraTxFailed : 1;     // 发送数据失败
        uint8_t loraJoin : 1;         // 正在入网
        uint8_t loraJoinSuccess : 1;  // 入网成功
        uint8_t loraJoinFailed : 1;   // 入网失败
        uint8_t loraLinkCheck : 1;    // 网络检测
        uint8_t loraDeviceTime : 1;   // 和服务器时间对时
        uint8_t loraDeviceTiming : 1;
        uint8_t loraMutexState : 1;  // lora发送数据锁状态
#if defined(CONFIG_DTU_485)
        uint8_t rs485SampleFirst : 1;  // 485第一轮采集完成，为了进行告警数据判断
#endif
#if defined(CONFIG_DTU_AI)
        uint8_t aiSampleFirst : 1;  // ai第一轮采集完成，为了进行告警数据判断
#endif
#if defined(CONFIG_DTU_DIN)
        uint8_t dinSampleFirst : 1;  // din第一轮采集完成，为了进行告警数据判断
#endif
    } flagBit;
} StytemState_t;

#if defined(CONFIG_DTU_485) || defined(CONFIG_DTU_DIN)
typedef struct {
    uint8_t arrtAlarmState : 4;
    uint8_t attrState : 4;
    uint32_t attrData;
} AttrSampleData_t;
#endif

#pragma pack()

typedef struct {
    volatile StytemState_t systemState;  // 系统的运行状态
    // volatile uint8_t appDataSize;                         // 应用数据大小
    // volatile uint8_t appData[LORAWAN_APP_DATA_MAX_SIZE];  // 应用缓存数组

    volatile TimerEvent_t txNextPacketTimer;  // 发送下一个数据包时间
    SemaphoreHandle_t loraTxMutex;            // LORA发送数据锁
#if defined(CONFIG_DTU_485)
    QueueHandle_t rs485TxQueue;  // 485发送数据队列
    // AttrSampleData_t AttrSampleData[SYSTEM_ATTRIBUTE_NUM];            //属性告警状态
#endif

#if defined(CONFIG_DTU_AI)
    AttrSampleData_t aiAttrSampleData[SYSTEM_AI_ATTRIBUTE_NUM];  // 属性告警状态
    uint16_t aiChannelConfig[SYSTEM_AI_ATTRIBUTE_NUM];           // ADS1115采集通道设置
#endif

#if defined(CONFIG_DTU_DIN)
    AttrSampleData_t dinAttrSampleData[SYSTEM_DIN_ATTRIBUTE_NUM];  // 属性告警状态
#endif

} SystemLoRaData_t;

extern SystemParmData_t SystemParmData;
// #define SystemAttriConfig SystemParmData;
extern SystemLoRaData_t SystemLoRaData;

extern log_level_t g_log_level;

uint8_t CRC8(unsigned char* ptr, unsigned char len);
void SystemParmDataStorage(uint32_t addr);
void SystemParmDataLoad(void);
SystemAttributeData_t* FindDeviceAttr(uint8_t attrId);
SystemAttributeData_t* GetEmptyDeviceAttr();
LoraDeviceModel_t* FindDeviceModel(int modelId);
LoraDeviceModel_t* GetEmptyDeviceModel();
void DumpSystemInfo();
void DumpAttrData();
void DumpDeviceModel();
void DumpDevices();
void DumpComParams();

void OsMutexRelease(SemaphoreHandle_t mutex_id);

#endif
